
import threading
import time
import yaml
from blivedm import BLiveClient, BaseHandler, DanmakuMessage

# 弹幕缓存队列，最多保存100条
DANMU_CACHE = []
DANMU_CACHE_MAX = 100
DANMU_CACHE_LOCK = threading.Lock()

def add_danmu(uname, msg):
    with DANMU_CACHE_LOCK:
        DANMU_CACHE.append({'uname': uname, 'msg': msg})
        if len(DANMU_CACHE) > DANMU_CACHE_MAX:
            DANMU_CACHE.pop(0)

def get_recent_danmu():
    with DANMU_CACHE_LOCK:
        return list(DANMU_CACHE)

class MyDanmuHandler(BaseHandler):
    def on_danmaku(self, client: BLiveClient, message: DanmakuMessage):
        add_danmu(message.uname, message.msg)
        # 可选：写入日志
        # with open('data/logs/danmu_live.log', 'a', encoding='utf-8') as f:
        #     f.write(f"[弹幕] {message.uname}：{message.msg}\n")


def _run_client_thread(client: BLiveClient):
    print(f"[blivedm] 线程模式启动监听: {client._room_id}")
    import asyncio
    while True:
        try:
            loop = asyncio.new_event_loop()
            asyncio.set_event_loop(loop)
            loop.run_until_complete(client.start())
        except Exception as e:
            print(f"[blivedm] 监听异常: {e}, 5秒后自动重连...")
            time.sleep(5)

async def _run_client_async(client: BLiveClient):
    rid = getattr(client, 'room_id', None) or getattr(client, '_room_id', None)
    print(f"[blivedm] 异步模式启动监听: {rid}")
    import asyncio
    while True:
        try:
            result = await client.start()
            if result is None:
                print(f"[blivedm] client.start() 返回 None，可能房间号无效或未开播，5秒后重试...")
                await asyncio.sleep(5)
                continue
        except Exception as e:
            print(f"[blivedm] 监听异常: {e}, 5秒后自动重连...")
            await asyncio.sleep(5)

def start_blivedm_listener(room_ids, use_async=False):
    print(f"[blivedm] start_blivedm_listener use_async={use_async} room_ids={room_ids}")
    import asyncio
    import yaml
    # 读取 cookie
    try:
        with open('config/config.yaml', 'r', encoding='utf-8') as f:
            config = yaml.safe_load(f)
        cookies = config.get('bilibili', {}).get('cookie', {})
        if not isinstance(cookies, dict):
            cookies = {}
    except Exception as e:
        print(f"[blivedm] 读取cookie失败: {e}")
        cookies = {}
    if isinstance(room_ids, int):
        room_ids = [room_ids]
    for rid in room_ids:
        client = BLiveClient(rid)
        # 设置cookie，兼容不同blivedm版本
        if cookies:
            if hasattr(client, 'set_cookies'):
                client.set_cookies(cookies)
            else:
                client.cookies = cookies
        # 兼容新版blivedm，使用add_handler注册
        if hasattr(client, 'add_handler'):
            client.add_handler(MyDanmuHandler())
        else:
            client.set_handler(MyDanmuHandler())
        if use_async:
            # 在主事件循环中注册
            asyncio.create_task(_run_client_async(client))
        else:
            t = threading.Thread(target=_run_client_thread, args=(client,), daemon=True)
            t.start()

# 自动从配置文件读取房间号并启动
def auto_start_from_config(config_path='config/config.yaml', use_async=False):
    print(f"[blivedm] auto_start_from_config use_async={use_async} config_path={config_path}")
    import asyncio
    def _start():
        print(f"[blivedm] _start() use_async={use_async}")
        try:
            with open(config_path, 'r', encoding='utf-8') as f:
                config = yaml.safe_load(f)
            room_id = config.get('bilibili', {}).get('room_id')
            if room_id:
                # 支持逗号分隔多房间
                if isinstance(room_id, str) and ',' in room_id:
                    room_ids = [int(r.strip()) for r in room_id.split(',') if r.strip().isdigit()]
                else:
                    room_ids = [int(room_id)]
                print(f"[blivedm] 自动监听房间: {room_ids}")
                start_blivedm_listener(room_ids, use_async=use_async)
            else:
                print("[blivedm] 配置文件未找到bilibili.room_id，未启动弹幕监听")
        except Exception as e:
            print(f"[blivedm] 配置读取或监听启动失败: {e}")
    if use_async:
        # FastAPI 场景下，主线程事件循环注册
        _start()
    else:
        t = threading.Thread(target=_start, daemon=True)
        t.start()

# 用于FastAPI或主程序自动启动
if __name__ == '__main__':
    auto_start_from_config()
    print('弹幕监听已启动，Ctrl+C 退出')
    while True:
        time.sleep(10)
